package com.iot.hmi.service;

import com.iot.hmi.entity.*;
import com.iot.hmi.pojo.IotItemVO;
import com.iot.hmi.pojo.LatestValueVO;
import com.iot.hmi.protocol.*;
import com.iot.hmi.utils.SqliteHelper;
import com.iot.hmi.utils.TimeHelper;

import java.sql.SQLException;
import java.text.ParseException;
import java.util.*;

public class HmiApiServiceImpl implements HmiApiService {
    @Override
    public void saveDeviceAndItems(IotDevice deviceInfo, List<IotDeviceItem> itemInfos) throws SQLException {
        SqliteHelper.deleteIotDevice(deviceInfo.getProtocolHost(), deviceInfo.getProtocolPort());
        SqliteHelper.deleteIotDeviceItem(deviceInfo.getProtocolHost(), deviceInfo.getProtocolPort());
        SqliteHelper.insertIotDevice(deviceInfo);
        final String refDeviceKey = SqliteHelper.refDeviceKey(
                deviceInfo.getProtocolHost(), deviceInfo.getProtocolPort()
        );
        for (IotDeviceItem item : itemInfos) {
            item.setRefDeviceKey(refDeviceKey);
            SqliteHelper.insertIotDeviceItem(item);
        }
    }

    @Override
    public void saveItemConfig(
            String host, Integer port, String address, IotItemConfig config
    ) throws SQLException {
        SqliteHelper.deleteIotItemConfig(host, port, address);
        final String refItemKey = SqliteHelper.refItemKey(host, port, address);
        config.setRefItemKey(refItemKey);
        SqliteHelper.insertIotItemConfig(config);
    }

    @Override
    public IotItemVO getItemConfig(String host, Integer port, String address) throws SQLException {
        IotItemVO result = new IotItemVO();
        result.setConfig(SqliteHelper.queryIotItemConfig(host, port, address));
        return result;
    }

    @Override
    public List<LatestValueVO> listLatestValue(String host, Integer port) throws SQLException {
        final List<IotDeviceItem> items = SqliteHelper.listIotDeviceItem(host, port);
        if (items.isEmpty()) {
            return new ArrayList<>(0);
        }
        List<LatestValueVO> result = new LinkedList<>();
        for (IotDeviceItem item : items) {
            try {
                final IotItemValue value = SqliteHelper.queryLatestValue(host, port, item.getItemAddress());
                if (value == null) {
                    continue;
                }
                LatestValueVO vo = new LatestValueVO();
                vo.setItemAddress(item.getItemAddress());
                vo.setCollectValue(value.getItemValue());
                vo.setCollectStamp(value.getValueStamp());
                result.add(vo);
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        return result;
    }

    @Override
    public List<IotDeviceItem> listItems(String host, Integer port) throws SQLException {
        final IotDevice device = SqliteHelper.queryIotDevice(host, port);
        if (device == null) {
            return new ArrayList<>(0);
        }
        return SqliteHelper.listIotDeviceItem(host, port);
    }

    @Override
    public List<IotItemValue> listValueByTimeRange(
            String protocolHost, Integer protocolPort, String itemAddress,
            String startTime, String endTime
    ) throws SQLException {
        try {
            return SqliteHelper.listIotItemValue(
                    protocolHost, protocolPort, itemAddress,
                    TimeHelper.datetime2stamp(startTime),
                    TimeHelper.datetime2stamp(endTime)
            );
        } catch (ParseException e) {
            return new ArrayList<>(0);
        }
    }

    @Override
    public AbstractProtocol protocolConnect(IotDevice device) {
        if (device.getProtocolType().contains("S7")) {
            final SiemensProtocolServiceImpl protocol = new SiemensProtocolServiceImpl(device);
            protocol.connect();
            return protocol;
        }
        if (device.getProtocolType().equals("ModbusTCP")) {
            final ModbusTCPServiceImpl protocol = new ModbusTCPServiceImpl(device);
            protocol.connect();
            return protocol;
        }
        return null;
    }

    @Override
    public ProtocolHandler startShader(AbstractProtocol protocol, List<IotDeviceItem> deviceItems, Integer period) {
        final ProtocolHandler protocolHandler = new ProtocolHandler(protocol, deviceItems, period);
        protocolHandler.startShader();
        protocolHandler.start();
        return protocolHandler;
    }
}
